﻿// Decompiled with JetBrains decompiler
// Type: Netick.NetworkHashSetSnapshot`1
// Assembly: Netick, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 6726ECA1-C773-4CF7-8952-E81B30D93B52
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.xml

using System.Collections;
using System.Collections.Generic;

#nullable disable
namespace Netick;

/// <summary>
/// A snapshot of the state of a <see cref="T:Netick.NetworkHashSet`1" /> collection. Note this must not be used outside the scope of an OnChanged call or a NetworkRender call.
/// </summary>
public struct NetworkHashSetSnapshot<T> : IEnumerable<T>, IEnumerable where T : unmanaged
{
  private unsafe int* Ptr;
  internal int _lengthDoubled;
  internal int _entrySizeWords;
  internal int _offsetToIterationList;

  public unsafe int Count => *this.Ptr;

  private unsafe NetworkHashSet<T>.Entry* GetEntryElementPointer(int index)
  {
    return (NetworkHashSet<T>.Entry*) (this.Ptr + 1 + index * this._entrySizeWords);
  }

  private unsafe NetworkHashSet<T>.Entry GetEntryElementData(int index)
  {
    return *(NetworkHashSet<T>.Entry*) (this.Ptr + 1 + index * this._entrySizeWords);
  }

  private unsafe int* GetIterationListElementPointer(int index)
  {
    return this.Ptr + this._offsetToIterationList + index;
  }

  private unsafe int GetIterationListElementData(int index)
  {
    return (this.Ptr + this._offsetToIterationList)[index];
  }

  internal unsafe NetworkHashSetSnapshot(int* p, int capacity)
  {
    this.Ptr = p;
    this._lengthDoubled = capacity * 2;
    this._entrySizeWords = NetickUtils.GetWordSize(sizeof (NetworkHashSet<T>.Entry));
    this._offsetToIterationList = 1 + this._lengthDoubled * this._entrySizeWords;
  }

  /// <summary>
  /// Determines whether the hashset snapshot contains a specific value.
  /// </summary>
  /// <param name="item">The object to locate in the snapshot.</param>
  /// <returns>true if item is found; otherwise, false.</returns>
  public bool Contains(T item) => this.FindEntry(item, out NetworkHashSet<T>.Entry _) != -1;

  private int FindEntry(T key, out NetworkHashSet<T>.Entry value)
  {
    int index = (key.GetHashCode() & int.MaxValue) % this._lengthDoubled;
    int num = index;
    do
    {
      NetworkHashSet<T>.Entry entryElementData = this.GetEntryElementData(index);
      if (entryElementData.IsEverUsed == 0)
      {
        value = new NetworkHashSet<T>.Entry();
        return -1;
      }
      if (!entryElementData.IsEmpty && EqualityComparer<T>.Default.Equals(entryElementData.Key, key))
      {
        value = entryElementData;
        return index;
      }
      index = (index + 1) % this._lengthDoubled;
    }
    while (index != num);
    value = new NetworkHashSet<T>.Entry();
    return -1;
  }

  public IEnumerator<T> GetEnumerator()
  {
    for (int i = 0; i < this.Count; ++i)
      yield return this.GetEntryElementData(this.GetIterationListElementData(i)).Key;
  }

  IEnumerator IEnumerable.GetEnumerator() => (IEnumerator) this.GetEnumerator();
}
